package com.feishi.core.media.javacv.util;

import com.feishi.core.util.common.LibraryUtil;
import org.bytedeco.javacpp.avcodec;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.FrameRecorder;
import org.bytedeco.javacv.OpenCVFrameGrabber;
import org.opencv.core.CvType;

import javax.sound.sampled.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.nio.Buffer;
import java.nio.ByteBuffer;

import static org.bytedeco.javacpp.FlyCapture2.FRAME_RATE;
import static org.bytedeco.javacpp.opencv_core.Mat;

/**
 * @version 1.0
 * @auth caixq
 * @time 18-5-3 11:25
 **/
public class JavaCvUtil {
    public static void closeRecord(FFmpegFrameRecorder recorder) {
        try {
            if (recorder != null) {
                recorder.stop();
            }
        } catch (org.bytedeco.javacv.FrameRecorder.Exception e) {
            System.out.println("关闭录制器失败");
        }
    }

    public void loadOpenCv(){
        LibraryUtil.load("lib"+ "NATIVE_LIBRARY_NAME"+".so");
    }
    public static byte[] BufferImgToBytes(BufferedImage image){
        return ((DataBufferByte) image.getRaster().getDataBuffer())
                .getData();
    }

    public static Mat bufImgToMat(BufferedImage image){

        byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
        Mat mat= new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3);
        ByteBuffer buf = mat.createBuffer();
        buf.put(pixels);
        return mat;
    }

    public static boolean openCamera(OpenCVFrameGrabber grabber) {
        try {
            grabber.start();
            return true;
        } catch (FrameGrabber.Exception e2) {
            if (grabber != null) {
                try {
                    grabber.restart();
                    return true;
                } catch (FrameGrabber.Exception e) {
                    try {
                        grabber.stop();
                    } catch (FrameGrabber.Exception e1) {
                    }finally {
                        return false;
                    }
                }
            }
        }
        return false;
    }

    public static TargetDataLine getDataLine(AudioFormat audioFormat) {
        /**
         * 设置音频编码器 最好是系统支持的格式，否则getLine() 会发生错误
         * 采样率:44.1k;采样率位数:16位;立体声(stereo);是否签名;true:
         * big-endian字节顺序,false:little-endian字节顺序(详见:ByteOrder类)
         */

        // 通过AudioSystem获取本地音频混合器信息
        Mixer.Info[] minfoSet = AudioSystem.getMixerInfo();
        // 通过AudioSystem获取本地音频混合器
        Mixer mixer = AudioSystem.getMixer(minfoSet[4]);
        // 通过设置好的音频编解码器获取数据线信息
        DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
        // 打开并开始捕获音频
        // 通过line可以获得更多控制权
        // 获取设备：TargetDataLine line
        TargetDataLine line = null;
        try {
            line = (TargetDataLine) mixer.getLine(dataLineInfo);
//          line = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
            line.open(audioFormat);
            return line;
        } catch (LineUnavailableException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static FFmpegFrameRecorder createFrameRecorder(String filePath, int width, int height) {

        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(filePath, width , height, 2);
        recorder.setInterleaved(true);
        //该参数用于降低延迟
        recorder.setVideoOption("tune", "zerolatency");
        //ultrafast(终极快)提供最少的压缩（低编码器CPU）和最大的视频流大小；而veryslow(非常慢)提供最佳的压缩（高编码器CPU）的同时降低视频流的大小
        recorder.setVideoOption("preset", "ultrafast");
        //设置视频编解码器(codec) -r 25 -设置帧率(frame rate) -b:v 500k -设置视频比特率(bit rate),比特率越高视频越清晰,视频体积也会变大,需要根据实际选择合理范围 -f flv
        recorder.setVideoOption("crf", "25");
        // 2000 kb/s, 720P视频的合理比特率范围
        recorder.setVideoBitrate(2000000);
        // h264编/解码器
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        // 封装格式flv
        recorder.setFormat("flv");
        // 视频帧率(保证视频质量的情况下最低25，低于25会出现闪屏)
        recorder.setFrameRate(FRAME_RATE);
        // 关键帧间隔，一般与帧率相同或者是视频帧率的两倍
        recorder.setGopSize(FRAME_RATE * 2);
        // 不可变(固定)音频比特率
        recorder.setAudioOption("crf", "0");
        // 最高质量
        recorder.setAudioQuality(0);
        // 音频比特率
        recorder.setAudioBitrate(192000);
        // 音频采样率
        recorder.setSampleRate(44100);
        // 双通道(立体声)
        recorder.setAudioChannels(2);
        // 音频编/解码器
        recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
        return recorder;
    }

    public static boolean openRecorder(FFmpegFrameRecorder recorder) {
        try {
            recorder.start();
            return true;
        } catch (FrameRecorder.Exception e2) {
            if (recorder != null) {
                try {
                    recorder.stop();
                    recorder.start();
                    return true;
                } catch (FrameRecorder.Exception e) {
                    try {
                        recorder.stop();
                    } catch (FrameRecorder.Exception e1) {
                    }
                }
            }

        }
        return false;
    }


}
